package dev.ece.suit.loader;

import java.io.InputStream;
import java.nio.FloatBuffer;
import java.util.Map;

import org.lwjgl.opengl.GL20;

import dev.ece.core.shader.Shader;
import dev.ece.suit.utils.ShaderFunctions;
import dev.ece.util.tools.BufferBuilder;

public class ModelDepthShader extends Shader {
	
	private static ModelDepthShader defaultModelDepthShader;
	
	public static ModelDepthShader getDefaultModelDepthShader() {
		if(defaultModelDepthShader == null) {
			defaultModelDepthShader = new ModelDepthShader(
					ModelDepthShader.class.getClassLoader().getResourceAsStream("shaders/model3ddepth.vert"),
					ModelDepthShader.class.getClassLoader().getResourceAsStream("shaders/model3ddepth.frag"),
					ShaderFunctions.getFunctions());
		}
		return defaultModelDepthShader;
	}
	
	/**
	 * 最多64个关节
	 */
	private FloatBuffer localSkeletonMatrixBuffer = BufferBuilder.buildFloatBuffer(ModelShader.MAX_SKELETON_COUNT * 16 * 4);
	
	private int localSkeletonMatrixHandler;
	
	public ModelDepthShader(StringBuffer vertexShaderString,
			StringBuffer pixelShaderString, Map<String, String> functions) {
		super(vertexShaderString, pixelShaderString, functions);
	}
	
	public ModelDepthShader(InputStream vertexShaderInputStream,
			InputStream pixelShaderInputStream, Map<String, String> functions) {
		super(vertexShaderInputStream, pixelShaderInputStream, functions);
	}
	
	@Override
	protected void onInitializeHandler(int program) {
		localSkeletonMatrixHandler = GL20.glGetUniformLocation(program, "ece_LocalSkeletonMatrix");
	}

	@Override
	protected void onBindAttribLocations(int program) {
		GL20.glBindAttribLocation(program, 0, "ece_Vertex");
		GL20.glBindAttribLocation(program, 1, "ece_BoneIds");
		GL20.glBindAttribLocation(program, 2, "ece_Weights");
	}

	public void glJointsLocalMatrix(Joint<?>[] joints) {
		if(joints != null) {
			for(Joint<?> joint:joints) {
				joint.getFinalTransform().store(localSkeletonMatrixBuffer);
			}
			this.localSkeletonMatrixBuffer.rewind();
			GL20.glUniformMatrix4fv(localSkeletonMatrixHandler, false, this.localSkeletonMatrixBuffer);
		}
	}

	public void setLocalSkeletonMatrixBuffer(
			FloatBuffer localSkeletonMatrixBuffer) {
		this.localSkeletonMatrixBuffer = localSkeletonMatrixBuffer;
	}

	@Override
	public void clearup() {
		GL20.glDeleteShader(localSkeletonMatrixHandler);
		super.clearup();
	}
	
}
